package moxl.parser.assemblers;

import moxl.parser.IncompleteDocumentException;
import moxl.parser.ParserException;
import moxl.parser.markup.Markup;
import moxl.parser.markup.TokenFedMarkupAssembler;
import moxl.tokenizer.Token;
import moxl.tokenizer.TokenStream;
import moxl.tokenizer.TokenizerException;
import moxl.tokenizer.xml.XmlTokenType;

public abstract class AbstractTokenFedMarkupAssembler<S, C extends AbstractAssemblerContext<S>> implements TokenFedMarkupAssembler
{
	public Markup assembleMarkupFromStream(TokenStream tstream) throws ParserException, TokenizerException
    {
		C ctx = createAssemblerContext(tstream);

		while (ctx.isNotFinished())
		{
			Token token;
			token = tstream.read();
			if (token == null)
			{
				throw new IncompleteDocumentException(tstream.getPosition());
			}
			ctx.setToken(token);
			XmlTokenType type = (XmlTokenType) token.getType();
			
			handleInput(type, ctx);
		}

		if (ctx.hasResult())
		{
			return ctx.getMarkup();
		}
		else
		{
			throw new IllegalStateException("No markup assembled");
		}
    }

	protected abstract void handleInput(XmlTokenType type, C ctx) throws ParserException, TokenizerException;

	protected abstract C createAssemblerContext(TokenStream tstream) throws ParserException, TokenizerException;
}
